package Factory;

import Registry.RpcRegistry;
import connection.zkConnection;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.util.List;
import java.util.Properties;

/**
 * @author: Lixy
 * @email: 1908598362@qq.com
 * @date: 2022/2/21 星期一 13:33
 */
public class RpcFactory {

    private static final Properties config = new Properties();

    private static  zkConnection CONNECTION;

    private static  RpcRegistry RPC_REGISTRY;

    private static final Properties services = new Properties();

    static {
    //获取classpath类路径下的配置文件输入流
        InputStream resource = RpcFactory.class.getClassLoader().getResourceAsStream("rpc.properties");
        try {
            //读取配置文件初始化配置对象
            config.load(resource);
            String serverIp = config.getProperty("registry.ip") == null ? "localhost" : config.getProperty("registry.ip");
            int serverPort = config.getProperty("registry.port") == null ? 9090 : Integer.parseInt(config.getProperty("registry.port"));
            String zkServer = config.getProperty("zk.server") == null ? "localhost:2181" : config.getProperty("zk.server");
            int zkSessionTimeout = config.getProperty("zk.sessionTimeout") == null ? 50000 :Integer.parseInt(config.getProperty("zk.sessionTimeout"));

            CONNECTION = new zkConnection(zkServer,zkSessionTimeout);

            RPC_REGISTRY = new RpcRegistry();

            RPC_REGISTRY.setIp(serverIp);

            RPC_REGISTRY.setPort(serverPort);

            RPC_REGISTRY.setConnection(CONNECTION);

            LocateRegistry.createRegistry(serverPort);

            //初始化zk的父节点/rpc
            List<String> children = CONNECTION.getConn().getChildren("/", false);

            if (!children.contains("rpc")){
                CONNECTION.getConn().create("/rpc",null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }

                InputStream inputStream = RpcFactory.class.getClassLoader().getResourceAsStream("rpc-service.properties");
                if (inputStream!=null){
                    services.load(inputStream);
                    for (Object key : services.keySet()){
                        Object value = services.get(key);
                        Class<Remote> serviceInterface = (Class<Remote>) Class.forName(key.toString());
                        Remote serviceObj = (Remote) Class.forName(value.toString()).newInstance();
                        RPC_REGISTRY.registerService(serviceInterface,serviceObj);
                    }
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
            //代码初始化出错 中断虚拟机
            throw new ExceptionInInitializerError(e);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    //提供一个快速的注册服务和创建客户端代理对象的静态工具方法
    public static void registerService(Class<? extends Remote> serviceInterface, Remote serviceObj) throws IOException, KeeperException, InterruptedException{
        RPC_REGISTRY.registerService(serviceInterface,serviceObj);
    }

    public static <T extends Remote> T getServiceProxy(Class<T> serviceInterface) throws IOException, KeeperException, InterruptedException, NotBoundException {
        return RPC_REGISTRY.getServiceProxy(serviceInterface);
    }
}
